<template>
  <div class="budget-detail">
    <div class="header">
      <el-button text :icon="ArrowLeft" @click="goBack">返回</el-button>
      <h1>{{ budget?.title || '记账详情' }}</h1>
      <div class="sub">
        <span v-if="plan">关联旅行计划：{{ plan.title }}</span>
      </div>
      <div class="header-actions">
        <el-button type="primary" @click="openEditBudget" :disabled="!budget">编辑记账</el-button>
      </div>
    </div>

    <el-card class="overview" shadow="never">
      <div class="amounts">
        <div class="amount-item">
          <div class="label">总预算</div>
          <div class="value">¥{{ budget?.amount }}</div>
        </div>
        <div class="amount-item">
          <div class="label">已使用</div>
          <div class="value used">¥{{ usedSum }}</div>
        </div>
      </div>
      <el-progress :percentage="progress" />
    </el-card>

    <el-card class="category-percentages" shadow="never" v-if="categoryPercentages.length > 0">
      <div id="category-chart" class="chart"></div>
    </el-card>

    <el-card class="expenses" shadow="never">
      <template #header>
        <div class="card-title">支出明细</div>
        <div class="filter-area">
          <div class="filters">
            <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期"
              end-placeholder="结束日期" size="small" style="width: 260px" @change="filterExpenses" />
            <el-select v-model="selectedCategory" placeholder="选择分类" clearable size="small" style="width: 120px"
              @change="filterExpenses">
              <el-option v-for="c in categoriesOptions" :key="c" :label="c" :value="c" />
            </el-select>
            <el-button size="small" @click="resetFilters">重置</el-button>
          </div>
          <div class="exp-actions">
            <el-button type="primary" size="small" @click="addRow">新增支出</el-button>
          </div>
        </div>
      </template>
      <el-table :data="expenseRows" v-if="expenseRows.length">
        <el-table-column label="日期" width="200">
          <template #default="{ row }">
            <template v-if="row.__editing">
              <el-date-picker v-model="row.date" type="date" placeholder="选择日期" value-format="YYYY-MM-DD"
                style="width: 160px" />
            </template>
            <template v-else>{{ row.date }}</template>
          </template>
        </el-table-column>
        <el-table-column label="分类" width="140">
          <template #default="{ row }">
            <template v-if="row.__editing">
              <el-select v-model="row.category" placeholder="分类" style="width: 127px">
                <el-option v-for="c in categoriesOptions" :key="c" :label="c" :value="c" />
              </el-select>
            </template>
            <template v-else>{{ row.category }}</template>
          </template>
        </el-table-column>
        <el-table-column label="描述">
          <template #default="{ row }">
            <template v-if="row.__editing">
              <el-input v-model="row.description" placeholder="描述" />
            </template>
            <template v-else>{{ row.description }}</template>
          </template>
        </el-table-column>
        <el-table-column label="金额" width="140">
          <template #default="{ row }">
            <template v-if="row.__editing">
              <el-input-number v-model="row.amount" :min="0" :step="10" controls-position="right"
                style="width: 127px" />
            </template>
            <template v-else>¥{{ row.amount }}</template>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="220" fixed="right">
          <template #default="{ row }">
            <template v-if="row.__editing">
              <el-button size="small" type="primary" @click="saveRow(row)">保存</el-button>
              <el-button size="small" @click="cancelRow(row)">取消</el-button>
            </template>
            <template v-else>
              <el-button size="small" @click="editRow(row)">编辑</el-button>
              <el-button size="small" type="danger" @click="deleteRow(row)">删除</el-button>
            </template>
          </template>
        </el-table-column>
      </el-table>
      <el-empty v-else description="暂无支出记录" />
    </el-card>

    <!-- 编辑预算弹框 -->
    <el-dialog v-model="editDialogVisible" title="编辑记账" width="520px">
      <el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="100px">
        <el-form-item label="标题" prop="title">
          <el-input v-model="editForm.title" />
        </el-form-item>
        <el-form-item label="总预算" prop="amount">
          <el-input-number v-model="editForm.amount" :min="0" :step="100" controls-position="right" />
        </el-form-item>
        <el-form-item label="关联计划" prop="travelPlanId">
          <el-select v-model="editForm.travelPlanId" placeholder="选择关联的旅行计划">
            <el-option v-for="p in travelPlans" :key="p.id" :label="p.title" :value="p.id" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="editDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveBudgetBasic">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, reactive, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ArrowLeft } from '@element-plus/icons-vue'
import { ElMessageBox } from 'element-plus'
import * as echarts from 'echarts'
import { getBudgetDetail, getExpenses, createExpense, updateExpense, deleteExpense, updateBudget } from '../../api/budget'
import { getTravelPlans } from '../../api/travelPlan'
import { authUtils } from '../../utils/auth'

const route = useRoute()
const router = useRouter()

const budgetId = computed(() => Number(route.params.id))
const budget = ref(null)


const travelPlans = ref([])
const plan = computed(() => budget.value ? travelPlans.value.find(p => p.id === budget.value.travelPlanId) : null)

// 用所有支出记录的总额计算已使用金额
const originalExpenses = ref([])
const usedSum = computed(() => originalExpenses.value.reduce((s, e) => s + Number(e.amount || 0), 0))
const progress = computed(() => {
  if (!budget.value) return 0
  return Math.min(100, Math.round((usedSum.value / (budget.value.amount || 1)) * 100))
})

// 计算各分类占总预算的百分比
const categoryPercentages = computed(() => {
  if (!budget.value || !originalExpenses.value.length) return []


  const categoryTotals = {}
  originalExpenses.value.forEach(expense => {
    if (!categoryTotals[expense.category]) {
      categoryTotals[expense.category] = 0
    }
    categoryTotals[expense.category] += Number(expense.amount || 0)
  })

  // 计算每个分类占总预算的百分比
  return Object.keys(categoryTotals).map(category => {
    const amount = categoryTotals[category]
    const percentage = Math.round((amount / (budget.value.amount || 1)) * 100)
    return {
      category,
      amount: amount.toFixed(2),
      percentage
    }
  }).sort((a, b) => b.percentage - a.percentage)
})

// 筛选相关变量
const dateRange = ref(null)
const selectedCategory = ref(null)
const expenseRows = ref([])

function filterExpenses() {
  let filtered = [...originalExpenses.value]

  // 按日期范围筛选
  if (dateRange.value && dateRange.value[0] && dateRange.value[1]) {
    const startDate = new Date(dateRange.value[0])
    const endDate = new Date(dateRange.value[1])
    filtered = filtered.filter(e => {
      const expenseDate = new Date(e.date)
      return expenseDate >= startDate && expenseDate <= endDate
    })
  }

  // 按分类筛选
  if (selectedCategory.value) {
    filtered = filtered.filter(e => e.category === selectedCategory.value)
  }

  expenseRows.value = filtered
}

function resetFilters() {
  dateRange.value = null
  selectedCategory.value = null
  filterExpenses()
}


const categoriesOptions = computed(() => {
  return ['住宿', '餐饮', '交通', '门票', '购物', '其他']
})

// 图表实例
let categoryChart = null

// 初始化分类占比环形图
const initCategoryChart = () => {
  const chartDom = document.getElementById('category-chart')
  if (!chartDom || !budget.value || !originalExpenses.value.length) return

  categoryChart = echarts.init(chartDom)

  // 准备数据
  const categoryData = categoryPercentages.value.map(item => ({
    value: Number(item.amount),
    name: item.category,
    itemStyle: {
      color: getCategoryColor(item.category)
    }
  }))

  const option = {
    title: {
      text: '分类占比统计',
      left: 'center',
      textStyle: {
        fontSize: 16,
        fontWeight: 'normal'
      }
    },
    tooltip: {
      trigger: 'item',
      formatter: '{a} <br/>{b}: ¥{c} ({d}%)'
    },
    legend: {
      orient: 'vertical',
      left: 'left',
      top: '15%'
    },
    series: [
      {
        name: '支出分类',
        type: 'pie',
        radius: ['40%', '70%'],
        center: ['50%', '60%'],
        avoidLabelOverlap: false,
        itemStyle: {
          borderRadius: 10,
          borderColor: '#fff',
          borderWidth: 2
        },
        label: {
          show: false,
          position: 'center'
        },
        emphasis: {
          label: {
            show: true,
            fontSize: 20,
            fontWeight: 'bold'
          }
        },
        labelLine: {
          show: false
        },
        data: categoryData
      }
    ]
  }

  categoryChart.setOption(option)
}

// 获取分类颜色
const getCategoryColor = (category) => {
  const colorMap = {
    '住宿': '#409eff',
    '餐饮': '#ffa200',
    '交通': '#eeff00',
    '门票': '#f56c6c',
    '购物': '#00ffcc',
    '其他': '#c0c4cc'
  }
  return colorMap[category] || '#909399'
}

// 窗口大小变化时重新调整图表大小
const handleResize = () => {
  categoryChart?.resize()
}

// 更新图表数据
const updateChart = () => {
  if (categoryChart && budget.value && originalExpenses.value.length) {
    const categoryData = categoryPercentages.value.map(item => ({
      value: Number(item.amount),
      name: item.category,
      itemStyle: {
        color: getCategoryColor(item.category)
      }
    }))

    categoryChart.setOption({
      series: [{
        data: categoryData
      }]
    })
  }
}

async function loadBudget() {
  try {
    const res = await getBudgetDetail(budgetId.value)
    const detail = res.data
    if (detail && detail.budget) {
      budget.value = detail.budget
      originalExpenses.value = (detail.expenses || []).map(e => ({ ...e, __editing: false }))
      filterExpenses()
    } else {
      budget.value = detail
    }
  } catch (e) {
    console.error('加载预算详情失败:', e)
    budget.value = null
  }
}

async function loadExpenses() {
  try {
    const res = await getExpenses({ budgetId: budgetId.value })
    const list = res.data
    originalExpenses.value = list.map(e => ({ ...e, __editing: false }))
    filterExpenses()
    // 加载数据后更新图表
    nextTick(() => {
      setTimeout(() => {
        if (!categoryChart) {
          initCategoryChart()
        } else {
          updateChart()
        }
      }, 100)
    })
  } catch (e) {
    console.error('加载支出失败:', e)
    originalExpenses.value = []
    expenseRows.value = []
  }
}

function editRow(row) {
  row.__backup = { ...row }
  row.__editing = true
}
function cancelRow(row) {
  if (row.__backup) Object.assign(row, row.__backup)
  row.__editing = false
}
async function saveRow(row) {
  const payload = {
    budgetId: budgetId.value,
    date: row.date,
    category: row.category,
    description: row.description,
    amount: Number(row.amount || 0)
  }
  try {
    if (row.id) {
      await updateExpense(row.id, payload)
    } else {
      const res = await createExpense(payload)
      const created = res.data
      if (created?.id) row.id = created.id
    }
    row.__editing = false
    await loadExpenses()
    await loadBudget()
  } catch (e) {
    console.error('保存支出失败:', e)
  }
}
async function deleteRow(row) {
  try {
    await ElMessageBox.confirm(
      `确定要删除这条支出记录吗？`,
      '删除确认',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }
    )
    await deleteExpense(row.id)
    await loadExpenses()
    await loadBudget()
  } catch (e) {
    if (e !== 'cancel') {
      console.error('删除支出失败:', e)
    }
  }
}
function addRow() {
  const newRow = {
    id: null,
    budgetId: budgetId.value,
    date: new Date().toISOString().slice(0, 10),
    category: categoriesOptions.value[0],
    description: '',
    amount: 0,
    __editing: true
  }
  expenseRows.value = [newRow, ...expenseRows.value]
}

// 弹框编辑预算基本信息
const editDialogVisible = ref(false)
const editFormRef = ref()
const editForm = reactive({ title: '', amount: 0, travelPlanId: null })
const editRules = {
  title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
  amount: [{ required: true, message: '请输入总预算', trigger: 'blur' }],
  travelPlanId: [{ required: true, message: '请选择关联计划', trigger: 'change' }],
}

function openEditBudget() {
  if (!budget.value) return
  editForm.title = budget.value.title
  editForm.amount = budget.value.amount
  editForm.travelPlanId = budget.value.travelPlanId
  editDialogVisible.value = true
}

async function saveBudgetBasic() {
  if (!editFormRef.value) return;

  // 使用 Promise 风格的 validate，避免嵌套异步回调
  try {
    await editFormRef.value.validate();
    if (!budget.value) return;

    const payload = {
      title: editForm.title,
      amount: editForm.amount,
      travelPlanId: editForm.travelPlanId
    };

    await updateBudget(budgetId.value, payload);
    editDialogVisible.value = false;
    await loadBudget();
  } catch (error) {
    if (error?.message === 'validate error') {
      // Element Plus 校验失败时会抛出此错误，无需额外处理
      return;
    }
    console.error('更新预算失败:', error);
  }
}

async function loadTravelPlans() {
  try {
    const currentUserId = authUtils.getCurrentUser()?.id
    const list = await getTravelPlans(currentUserId ? { userId: currentUserId } : {})
    travelPlans.value = list
  } catch (e) {
    console.error('加载旅行计划失败:', e)
    travelPlans.value = []
  }
}

watch(budgetId, () => {
  loadBudget()
  loadExpenses()
  loadTravelPlans()
}, { immediate: true })

onMounted(() => {
  // 监听窗口大小变化
  window.addEventListener('resize', handleResize)
})

onBeforeUnmount(() => {
  // 销毁图表实例
  categoryChart?.dispose()
  // 移除事件监听
  window.removeEventListener('resize', handleResize)
})

const goBack = () => router.back()
</script>

<style scoped>
.budget-detail {
  padding: 20px;
  max-width: 1000px;
  margin: 0 auto;
}

.header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.header h1 {
  margin: 0;
  font-size: 24px;
  font-weight: 700;
}

.sub {
  color: #909399;
}

.header-actions {
  margin-left: auto;
}

.overview {
  margin: 12px 0;
}

.amounts {
  display: flex;
  gap: 24px;
  margin-bottom: 8px;
}

.amount-item .label {
  color: #909399;
  font-size: 12px;
}

.amount-item .value {
  font-size: 20px;
  font-weight: 700;
}

.amount-item .value.used {
  color: #F56C6C;
}

.category-percentages {
  margin-top: 16px;
}

.chart {
  width: 100%;
  height: 400px;
  min-height: 400px;
}

.card-title {
  font-weight: 600;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .chart {
    height: 300px;
  }
}

.expenses {
  margin-top: 16px;
}

.filter-area {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 8px;
}

.filters {
  display: flex;
  gap: 8px;
  align-items: center;
}

.exp-actions {
  display: flex;
  justify-content: flex-end;
}

.category-card {
  padding: 12px;
}

.cat-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.cat-header .name {
  font-size: 14px;
  font-weight: 700;
}

.cat-header .vals {
  font-size: 14px;
  color: #909399;
}

.amount-text {
  font-size: 12px;
  color: #909399;
  margin-top: 8px;
}
</style>